# 整体框架
Passthrough HALs 的存在,主要是为了复用传统 HAL 的实现。HAL 层以进程的形式存在,内部有一个 HwBinder 服务端对象,对外提供 HwBinder 远程调用服务。Framework 通过 HwBinder 远程调用到 HAL 中的函数,这些函数会去加载传统 HAL 实现来操作具体硬件。整体架构如下:
在源码下 hardware/interfaces/vibrator/1.0
目录下,就是一个振动器的 Passthrough HALs 实现。接下来我们就来分析其源码。
# HAL 层服务端实现
源码的整体结构如下:
我们从 hardware/interfaces/vibrator/1.0/default/Android.bp
下手:
cc_library_shared {
name: "android.hardware.vibrator@1.0-impl",
defaults: ["hidl_defaults"],
vendor: true,
relative_install_path: "hw",
srcs: ["Vibrator.cpp"],
shared_libs: [
"libhidlbase",
"libhidltransport",
"liblog",
"libutils",
"libhardware",
"android.hardware.vibrator@1.0",
],
}
cc_binary {
name: "android.hardware.vibrator@1.0-service",
defaults: ["hidl_defaults"],
init_rc: ["android.hardware.vibrator@1.0-service.rc"],
vendor: true,
relative_install_path: "hw",
srcs: ["service.cpp"],
shared_libs: [
"libhidlbase",
"libhidltransport",
"liblog",
"libutils",
"libhardware",
"android.hardware.vibrator@1.0",
],
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
一个共享库 android.hardware.vibrator@1.0-impl
,一个 native 可执行程序 android.hardware.vibrator@1.3-service.coral
。
android.hardware.vibrator@1.0-impl
共享库中,主要包含了 Vibrator HwBinder 服务端对象,对上提供 HwBinder 远程调用服务,对下调用传统 Hal 操作具体硬件。
android.hardware.vibrator@1.0-service
可执行程序对应的源码是 hardware/interfaces/vibrator/1.0/default/service.cpp
:
#define LOG_TAG "android.hardware.vibrator@1.0-service"
#include <android/hardware/vibrator/1.0/IVibrator.h>
#include <hidl/LegacySupport.h>
using android::hardware::vibrator::V1_0::IVibrator;
using android::hardware::defaultPassthroughServiceImplementation;
int main() {
return defaultPassthroughServiceImplementation<IVibrator>();
}
2
3
4
5
6
7
8
9
10
11
主函数的实现很简单,就是调用 defaultPassthroughServiceImplementation
,其实现如下:
// system/libhidl/transport/include/hidl/LegacySupport.h
template<class Interface>
__attribute__((warn_unused_result))
status_t defaultPassthroughServiceImplementation(size_t maxThreads = 1) {
return defaultPassthroughServiceImplementation<Interface>("default", maxThreads);
}
template <class Interface>
__attribute__((warn_unused_result)) status_t defaultPassthroughServiceImplementation(
const std::string& name, size_t maxThreads = 1) {
configureRpcThreadpool(maxThreads, true);
status_t result = registerPassthroughServiceImplementation<Interface>(name);
if (result != OK) {
return result;
}
joinRpcThreadpool();
return UNKNOWN_ERROR;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
这里会:
- 配置好 HwBinder 线程
- 调用 registerPassthroughServiceImplementation 函数
// system/libhidl/transport/include/hidl/LegacySupport.h
template <class Interface>
__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
const std::string& name = "default") {
return details::registerPassthroughServiceImplementation<Interface>(
[](const sp<Interface>& service, const std::string& name) {
return service->registerAsService(name);
},
name);
}
2
3
4
5
6
7
8
9
10
11
这里接着调用 registerPassthroughServiceImplementation 函数,同时传入了一个 lamda 表达式。
// system/libhidl/transport/include/hidl/LegacySupport.h
template <class Interface, typename Func>
__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
Func registerServiceCb, const std::string& name = "default") {
sp<Interface> service = Interface::getService(name, true /* getStub */);
if (service == nullptr) {
ALOGE("Could not get passthrough implementation for %s/%s.",
Interface::descriptor, name.c_str());
return EXIT_FAILURE;
}
LOG_FATAL_IF(service->isRemote(), "Implementation of %s/%s is remote!",
Interface::descriptor, name.c_str());
status_t status = registerServiceCb(service, name);
if (status == OK) {
ALOGI("Registration complete for %s/%s.",
Interface::descriptor, name.c_str());
} else {
ALOGE("Could not register service %s/%s (%d).",
Interface::descriptor, name.c_str(), status);
}
return status;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
这里的模版 Interface 就是前面传入的 IVibrator,接着调用 IVibrator::getService 函数,这个是编译系统生成的代码:
// out/soong/.intermediates/hardware/interfaces/vibrator/1.0/android.hardware.vibrator@1.0_genc++/gen/android/hardware/vibrator/1.0/VibratorAll.cpp
::android::sp<IVibrator> IVibrator::getService(const std::string &serviceName, const bool getStub) {
return ::android::hardware::details::getServiceInternal<BpHwVibrator>(serviceName, true, getStub);
}
2
3
4
// system/libhidl/transport/include/hidl/HidlTransportSupport.h
template <typename BpType, typename IType = typename BpType::Pure,
typename = std::enable_if_t<std::is_same<i_tag, typename IType::_hidl_tag>::value>,
typename = std::enable_if_t<std::is_same<bphw_tag, typename BpType::_hidl_tag>::value>>
sp<IType> getServiceInternal(const std::string& instance, bool retry, bool getStub) {
using ::android::hidl::base::V1_0::IBase;
//descriptor: android.hardware.vibrator@1.0::IVibrator
sp<IBase> base = getRawServiceInternal(IType::descriptor, instance, retry, getStub);
if (base == nullptr) {
return nullptr;
}
if (base->isRemote()) {
// getRawServiceInternal guarantees we get the proper class
return sp<IType>(new BpType(getOrCreateCachedBinder(base.get())));
}
return IType::castFrom(base);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
接着调用 getRawServiceInternal
:
// system/libhidl/transport/ServiceManagement.cpp
// 参数 getStub 为 true
sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,
const std::string& instance,
bool retry, bool getStub) {
using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport;
using ::android::hidl::manager::V1_0::IServiceManager;
sp<Waiter> waiter;
sp<IServiceManager1_1> sm;
Transport transport = Transport::EMPTY;
if (kIsRecovery) {
transport = Transport::PASSTHROUGH;
} else {
// 获取 HwServiceManager 代理端对象。
sm = defaultServiceManager1_1();
if (sm == nullptr) {
ALOGE("getService: defaultServiceManager() is null");
return nullptr;
}
// 获取 vintf 中的 transport 参数
// passthrough HAL 是 hwbinder
Return<Transport> transportRet = sm->getTransport(descriptor, instance);
if (!transportRet.isOk()) {
ALOGE("getService: defaultServiceManager()->getTransport returns %s",
transportRet.description().c_str());
return nullptr;
}
transport = transportRet;
}
// true
const bool vintfHwbinder = (transport == Transport::HWBINDER);
// false
const bool vintfPassthru = (transport == Transport::PASSTHROUGH);
#ifdef ENFORCE_VINTF_MANIFEST
#ifdef LIBHIDL_TARGET_DEBUGGABLE
const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
const bool trebleTestingOverride = env && !strcmp(env, "true");
const bool vintfLegacy = (transport == Transport::EMPTY) && trebleTestingOverride;
#else // ENFORCE_VINTF_MANIFEST but not LIBHIDL_TARGET_DEBUGGABLE
const bool trebleTestingOverride = false;
const bool vintfLegacy = false;
#endif // LIBHIDL_TARGET_DEBUGGABLE
#else // not ENFORCE_VINTF_MANIFEST
const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
const bool trebleTestingOverride = env && !strcmp(env, "true");
const bool vintfLegacy = (transport == Transport::EMPTY);
#endif // ENFORCE_VINTF_MANIFEST
// getStub 为 ture,for 循环不进入
for (int tries = 0; !getStub && (vintfHwbinder || vintfLegacy); tries++) {
if (waiter == nullptr && tries > 0) {
waiter = new Waiter(descriptor, instance, sm);
}
if (waiter != nullptr) {
waiter->reset(); // don't reorder this -- see comments on reset()
}
Return<sp<IBase>> ret = sm->get(descriptor, instance);
if (!ret.isOk()) {
ALOGE("getService: defaultServiceManager()->get returns %s for %s/%s.",
ret.description().c_str(), descriptor.c_str(), instance.c_str());
break;
}
sp<IBase> base = ret;
if (base != nullptr) {
Return<bool> canCastRet =
details::canCastInterface(base.get(), descriptor.c_str(), true /* emitError */);
if (canCastRet.isOk() && canCastRet) {
if (waiter != nullptr) {
waiter->done();
}
return base; // still needs to be wrapped by Bp class.
}
if (!handleCastError(canCastRet, descriptor, instance)) break;
}
// In case of legacy or we were not asked to retry, don't.
if (vintfLegacy || !retry) break;
if (waiter != nullptr) {
ALOGI("getService: Trying again for %s/%s...", descriptor.c_str(), instance.c_str());
waiter->wait(true /* timeout */);
}
}
if (waiter != nullptr) {
waiter->done();
}
// getStub 为 true,进入
if (getStub || vintfPassthru || vintfLegacy) {
const sp<IServiceManager> pm = getPassthroughServiceManager();
if (pm != nullptr) {
sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr);
if (!getStub || trebleTestingOverride) {
base = wrapPassthrough(base);
}
return base;
}
}
return nullptr;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// system/libhidl/transport/ServiceManagement.cpp
sp<IServiceManager1_0> getPassthroughServiceManager() {
return getPassthroughServiceManager1_1();
}
sp<IServiceManager1_1> getPassthroughServiceManager1_1() {
static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
return manager;
}
2
3
4
5
6
7
8
就是 new 一个 PassthroughServiceManager,PassthroughServiceManager 实现了 IServiceManager 接口。
接着调用 PassthroughServiceManager 的 get 函数:
Return<sp<IBase>> get(const hidl_string& fqName,
const hidl_string& name) override {
sp<IBase> ret = nullptr;
openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {
IBase* (*generator)(const char* name);
*(void **)(&generator) = dlsym(handle, sym.c_str());
if(!generator) {
const char* error = dlerror();
LOG(ERROR) << "Passthrough lookup opened " << lib
<< " but could not find symbol " << sym << ": "
<< (error == nullptr ? "unknown error" : error);
dlclose(handle);
return true;
}
ret = (*generator)(name.c_str());
if (ret == nullptr) {
dlclose(handle);
return true; // this module doesn't provide this instance name
}
// Actual fqname might be a subclass.
// This assumption is tested in vts_treble_vintf_test
using ::android::hardware::details::getDescriptor;
std::string actualFqName = getDescriptor(ret.get());
CHECK(actualFqName.size() > 0);
registerReference(actualFqName, name);
return false;
});
return ret;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
调用 openlib 并传入一个 lamda:
// fqName: android.hardware.vibrator@1.0::IVibrator
static void openLibs(
const std::string& fqName,
const std::function<bool /* continue */ (void* /* handle */, const std::string& /* lib */,
const std::string& /* sym */)>& eachLib) {
//fqName looks like android.hardware.foo@1.0::IFoo
size_t idx = fqName.find("::");
if (idx == std::string::npos ||
idx + strlen("::") + 1 >= fqName.size()) {
LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
return;
}
// android.hardware.vibrator@1.0
std::string packageAndVersion = fqName.substr(0, idx);
// IVibrator
std::string ifaceName = fqName.substr(idx + strlen("::"));
// android.hardware.vibrator@1.0-impl
const std::string prefix = packageAndVersion + "-impl";
// HIDL_FETCH_IVibrator
const std::string sym = "HIDL_FETCH_" + ifaceName;
constexpr int dlMode = RTLD_LAZY;
void* handle = nullptr;
dlerror(); // clear
static std::string halLibPathVndkSp = android::base::StringPrintf(
HAL_LIBRARY_PATH_VNDK_SP_FOR_VERSION, details::getVndkVersionStr().c_str());
// 从固定的几个目录查找 so 库
std::vector<std::string> paths = {
HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, halLibPathVndkSp,
#ifndef __ANDROID_VNDK__
HAL_LIBRARY_PATH_SYSTEM,
#endif
};
#ifdef LIBHIDL_TARGET_DEBUGGABLE
const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
const bool trebleTestingOverride = env && !strcmp(env, "true");
if (trebleTestingOverride) {
// Load HAL implementations that are statically linked
handle = dlopen(nullptr, dlMode);
if (handle == nullptr) {
const char* error = dlerror();
LOG(ERROR) << "Failed to dlopen self: "
<< (error == nullptr ? "unknown error" : error);
} else if (!eachLib(handle, "SELF", sym)) {
return;
}
const char* vtsRootPath = std::getenv("VTS_ROOT_PATH");
if (vtsRootPath && strlen(vtsRootPath) > 0) {
const std::string halLibraryPathVtsOverride =
std::string(vtsRootPath) + HAL_LIBRARY_PATH_SYSTEM;
paths.insert(paths.begin(), halLibraryPathVtsOverride);
}
}
#endif
// 从固定的几个目录查找 android.hardware.vibrator@1.0-impl.so 库
for (const std::string& path : paths) {
std::vector<std::string> libs = findFiles(path, prefix, ".so");
for (const std::string &lib : libs) {
const std::string fullPath = path + lib;
if (kIsRecovery || path == HAL_LIBRARY_PATH_SYSTEM) {
// dlopen 打开 so 库
handle = dlopen(fullPath.c_str(), dlMode);
} else {
#if !defined(__ANDROID_RECOVERY__)
handle = android_load_sphal_library(fullPath.c_str(), dlMode);
#endif
}
if (handle == nullptr) {
const char* error = dlerror();
LOG(ERROR) << "Failed to dlopen " << lib << ": "
<< (error == nullptr ? "unknown error" : error);
continue;
}
// 调用传入的回调
if (!eachLib(handle, lib, sym)) {
return;
}
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
再看 lamda 回调:
openLibs(fqName, [&](void* handle, const std::string &lib, const std::string &sym) {
IBase* (*generator)(const char* name);
// 加载 HIDL_FETCH_IVibrator 符号
*(void **)(&generator) = dlsym(handle, sym.c_str());
if(!generator) {
const char* error = dlerror();
LOG(ERROR) << "Passthrough lookup opened " << lib
<< " but could not find symbol " << sym << ": "
<< (error == nullptr ? "unknown error" : error);
dlclose(handle);
return true;
}
// 调用 HIDL_FETCH_IVibrator 函数
ret = (*generator)(name.c_str());
if (ret == nullptr) {
dlclose(handle);
return true; // this module doesn't provide this instance name
}
// Actual fqname might be a subclass.
// This assumption is tested in vts_treble_vintf_test
using ::android::hardware::details::getDescriptor;
std::string actualFqName = getDescriptor(ret.get());
CHECK(actualFqName.size() > 0);
registerReference(actualFqName, name);
return false;
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
HIDL_FETCH_IVibrator 函数实现在 hardware/interfaces/vibrator/1.0/default/Vibrator.cpp
:
IVibrator* HIDL_FETCH_IVibrator(const char * /*hal*/) {
vibrator_device_t *vib_device;
const hw_module_t *hw_module = nullptr;
int ret = hw_get_module(VIBRATOR_HARDWARE_MODULE_ID, &hw_module);
if (ret == 0) {
ret = vibrator_open(hw_module, &vib_device);
if (ret != 0) {
ALOGE("vibrator_open failed: %d", ret);
}
} else {
ALOGE("hw_get_module %s failed: %d", VIBRATOR_HARDWARE_MODULE_ID, ret);
}
if (ret == 0) {
return new Vibrator(vib_device);
} else {
ALOGE("Passthrough failed to open legacy HAL.");
return nullptr;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
这里就是加载传统 HAL 实现,并将传统 HAL 包装成一个 Vibrator 对象返回。
回到开始:
// system/libhidl/transport/include/hidl/LegacySupport.h
template <class Interface>
__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
const std::string& name = "default") {
return details::registerPassthroughServiceImplementation<Interface>(
[](const sp<Interface>& service, const std::string& name) {
return service->registerAsService(name);
},
name);
}
template <class Interface, typename Func>
__attribute__((warn_unused_result)) status_t registerPassthroughServiceImplementation(
Func registerServiceCb, const std::string& name = "default") {
// 获取到 Vibrator
sp<Interface> service = Interface::getService(name, true /* getStub */);
if (service == nullptr) {
ALOGE("Could not get passthrough implementation for %s/%s.",
Interface::descriptor, name.c_str());
return EXIT_FAILURE;
}
LOG_FATAL_IF(service->isRemote(), "Implementation of %s/%s is remote!",
Interface::descriptor, name.c_str());
// 调用 lamda 注册
status_t status = registerServiceCb(service, name);
if (status == OK) {
ALOGI("Registration complete for %s/%s.",
Interface::descriptor, name.c_str());
} else {
ALOGE("Could not register service %s/%s (%d).",
Interface::descriptor, name.c_str(), status);
}
return status;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
获取到 Vibrator 后,接着调用 lamda 注册服务。
::android::status_t IVibrator::registerAsService(const std::string &serviceName) {
return ::android::hardware::details::registerAsServiceInternal(this, serviceName);
}
2
3
这里将 Vibrator 服务注册到 HwServiceManager,具体细节我们就不去深入,不是我们的重点。
# Framework 层客户端实现
对于客户端,我们只要知道 Hal 对外提供的接口即可,这个接口又 hardware/interfaces/vibrator/1.0/IVibrator.hal
描述:
package android.hardware.vibrator@1.0;
interface IVibrator {
/**
* Turn on vibrator
*
* This function must only be called after the previous timeout has expired or
* was canceled (through off()).
* @param timeout_ms number of milliseconds to vibrate.
* @return vibratorOnRet whether vibrator command was successful or not.
*/
on(uint32_t timeoutMs) generates (Status vibratorOnRet);
/**
* Turn off vibrator
*
* Cancel a previously-started vibration, if any.
* @return vibratorOffRet whether vibrator command was successful or not.
*/
off() generates (Status vibratorOffRet);
/**
* Returns whether the vibrator supports changes to its vibrational amplitude.
*/
supportsAmplitudeControl() generates (bool supports);
/**
* Sets the motor's vibrational amplitude.
*
* Changes the force being produced by the underlying motor.
*
* @param amplitude The unitless force setting. Note that this number must
* be between 1 and 255, inclusive. If the motor does not
* have exactly 255 steps, it must do it's best to map it
* onto the number of steps it does have.
* @return status Whether the command was successful or not. Must return
* Status::UNSUPPORTED_OPERATION if setting the amplitude is
* not supported by the device.
*/
setAmplitude(uint8_t amplitude) generates (Status status);
/**
* Fire off a predefined haptic event.
*
* @param event The type of haptic event to trigger.
* @return status Whether the effect was successfully performed or not. Must
* return Status::UNSUPPORTED_OPERATION is the effect is not
* supported.
* @return lengthMs The length of time the event is expected to take in
* milliseconds. This doesn't need to be perfectly accurate,
* but should be a reasonable approximation. Should be a
* positive, non-zero value if the returned status is
* Status::OK, and set to 0 otherwise.
*/
perform(Effect effect, EffectStrength strength) generates (Status status, uint32_t lengthMs);
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
frameworks/base/services/core/java/com/android/server/VibratorService.java
本身是一个 Binder 服务端向 App 提供服务,同时也是一个 HwBinder 客户端通过 JNI 访问到 HAL 服务端。
public class VibratorService extends IVibratorService.Stub
implements InputManager.InputDeviceListener {
// ......
static native boolean vibratorExists();
static native void vibratorInit();
static native void vibratorOn(long milliseconds);
static native void vibratorOff();
static native boolean vibratorSupportsAmplitudeControl();
static native void vibratorSetAmplitude(int amplitude);
static native long vibratorPerformEffect(long effect, long strength);
static native boolean vibratorSupportsExternalControl();
static native void vibratorSetExternalControl(boolean enabled);
// ......
}
2
3
4
5
6
7
8
9
10
11
12
13
14
VibratorService 中有多个 native 方法,这些方法用于远程调用 Hal 层。
对应的 JNI 函数实现在 frameworks/base/services/core/jni/com_android_server_VibratorService.cpp
:
#define LOG_TAG "VibratorService"
#include <android/hardware/vibrator/1.0/IVibrator.h>
#include <android/hardware/vibrator/1.0/types.h>
#include <android/hardware/vibrator/1.0/IVibrator.h>
#include <android/hardware/vibrator/1.1/types.h>
#include <android/hardware/vibrator/1.2/IVibrator.h>
#include <android/hardware/vibrator/1.2/types.h>
#include <android/hardware/vibrator/1.3/IVibrator.h>
#include "jni.h"
#include <nativehelper/JNIHelp.h>
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/vibrator.h>
#include <inttypes.h>
#include <stdio.h>
using android::hardware::Return;
using android::hardware::vibrator::V1_0::EffectStrength;
using android::hardware::vibrator::V1_0::Status;
using android::hardware::vibrator::V1_1::Effect_1_1;
namespace V1_0 = android::hardware::vibrator::V1_0;
namespace V1_1 = android::hardware::vibrator::V1_1;
namespace V1_2 = android::hardware::vibrator::V1_2;
namespace V1_3 = android::hardware::vibrator::V1_3;
namespace android {
static constexpr int NUM_TRIES = 2;
// Creates a Return<R> with STATUS::EX_NULL_POINTER.
template<class R>
inline Return<R> NullptrStatus() {
using ::android::hardware::Status;
return Return<R>{Status::fromExceptionCode(Status::EX_NULL_POINTER)};
}
// Helper used to transparently deal with the vibrator HAL becoming unavailable.
template<class R, class I, class... Args0, class... Args1>
Return<R> halCall(Return<R> (I::* fn)(Args0...), Args1&&... args1) {
// Assume that if getService returns a nullptr, HAL is not available on the
// device.
static sp<I> sHal = I::getService();
static bool sAvailable = sHal != nullptr;
if (!sAvailable) {
return NullptrStatus<R>();
}
// Return<R> doesn't have a default constructor, so make a Return<R> with
// STATUS::EX_NONE.
using ::android::hardware::Status;
Return<R> ret{Status::fromExceptionCode(Status::EX_NONE)};
// Note that ret is guaranteed to be changed after this loop.
for (int i = 0; i < NUM_TRIES; ++i) {
ret = (sHal == nullptr) ? NullptrStatus<R>()
: (*sHal.*fn)(std::forward<Args1>(args1)...);
if (ret.isOk()) {
break;
}
ALOGE("Failed to issue command to vibrator HAL. Retrying.");
// Restoring connection to the HAL.
sHal = I::tryGetService();
}
return ret;
}
template<class R>
bool isValidEffect(jlong effect) {
if (effect < 0) {
return false;
}
R val = static_cast<R>(effect);
auto iter = hardware::hidl_enum_range<R>();
return val >= *iter.begin() && val <= *std::prev(iter.end());
}
static void vibratorInit(JNIEnv /* env */, jobject /* clazz */)
{
halCall(&V1_0::IVibrator::ping).isOk();
}
static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */)
{
return halCall(&V1_0::IVibrator::ping).isOk() ? JNI_TRUE : JNI_FALSE;
}
static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms)
{
Status retStatus = halCall(&V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR);
if (retStatus != Status::OK) {
ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
}
}
static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */)
{
Status retStatus = halCall(&V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR);
if (retStatus != Status::OK) {
ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
}
}
static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jobject) {
return halCall(&V1_0::IVibrator::supportsAmplitudeControl).withDefault(false);
}
static void vibratorSetAmplitude(JNIEnv*, jobject, jint amplitude) {
Status status = halCall(&V1_0::IVibrator::setAmplitude, static_cast<uint32_t>(amplitude))
.withDefault(Status::UNKNOWN_ERROR);
if (status != Status::OK) {
ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").",
static_cast<uint32_t>(status));
}
}
static jboolean vibratorSupportsExternalControl(JNIEnv*, jobject) {
return halCall(&V1_3::IVibrator::supportsExternalControl).withDefault(false);
}
static void vibratorSetExternalControl(JNIEnv*, jobject, jboolean enabled) {
Status status = halCall(&V1_3::IVibrator::setExternalControl, static_cast<uint32_t>(enabled))
.withDefault(Status::UNKNOWN_ERROR);
if (status != Status::OK) {
ALOGE("Failed to set vibrator external control (%" PRIu32 ").",
static_cast<uint32_t>(status));
}
}
static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength) {
Status status;
uint32_t lengthMs;
auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) {
status = retStatus;
lengthMs = retLengthMs;
};
EffectStrength effectStrength(static_cast<EffectStrength>(strength));
Return<void> ret;
if (isValidEffect<V1_0::Effect>(effect)) {
ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect),
effectStrength, callback);
} else if (isValidEffect<Effect_1_1>(effect)) {
ret = halCall(&V1_1::IVibrator::perform_1_1, static_cast<Effect_1_1>(effect),
effectStrength, callback);
} else if (isValidEffect<V1_2::Effect>(effect)) {
ret = halCall(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(effect),
effectStrength, callback);
} else if (isValidEffect<V1_3::Effect>(effect)) {
ret = halCall(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(effect),
effectStrength, callback);
} else {
ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")",
static_cast<int32_t>(effect));
return -1;
}
if (!ret.isOk()) {
ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect));
return -1;
}
if (status == Status::OK) {
return lengthMs;
} else if (status != Status::UNSUPPORTED_OPERATION) {
// Don't warn on UNSUPPORTED_OPERATION, that's a normal event and just means the motor
// doesn't have a pre-defined waveform to perform for it, so we should just give the
// opportunity to fall back to the framework waveforms.
ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32
", error=%" PRIu32 ").", static_cast<int64_t>(effect),
static_cast<int32_t>(strength), static_cast<uint32_t>(status));
}
return -1;
}
static const JNINativeMethod method_table[] = {
{ "vibratorExists", "()Z", (void*)vibratorExists },
{ "vibratorInit", "()V", (void*)vibratorInit },
{ "vibratorOn", "(J)V", (void*)vibratorOn },
{ "vibratorOff", "()V", (void*)vibratorOff },
{ "vibratorSupportsAmplitudeControl", "()Z", (void*)vibratorSupportsAmplitudeControl},
{ "vibratorSetAmplitude", "(I)V", (void*)vibratorSetAmplitude},
{ "vibratorPerformEffect", "(JJ)J", (void*)vibratorPerformEffect},
{ "vibratorSupportsExternalControl", "()Z", (void*)vibratorSupportsExternalControl},
{ "vibratorSetExternalControl", "(Z)V", (void*)vibratorSetExternalControl},
};
int register_android_server_VibratorService(JNIEnv *env)
{
return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
method_table, NELEM(method_table));
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
所有的函数都通过 hascall 来实现,hascall 中会去从 HwServiceManager 中去获取 Vibrator Hal 的代理对象,然后通过这个代理对象发起远程调用,从而调用到 HAL 层。